//
//  main.cpp
//  distributed-gradient
//
//  Created by Emanuele Vespa on 6/20/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#include <iostream>
#include "subgradient_horizon.h"

using namespace std;

int main(int argc, const char * argv[])
{

    
    int num_parmods = 3; 
    int horizon = 2;
    
    ParMod * parmods = new ParMod(num_parmods, horizon);
    
    for(int i = 0; i < num_parmods; i++){
        
        parmods[i] = *new ParMod(3, horizon);
        parmods[i].id = i;
        
    }
    
    // parameters: alfa - beta 
    
    parmods[0].setPerformanceCosts(4.0, 2.5);
    parmods[1].setPerformanceCosts(12, 1.4);
    parmods[2].setPerformanceCosts(3, 1.1);
    
    // parameters: Tcalc - Control step
    
//    parmods[0].setTcalc(15, 0);
//    parmods[1].setTcalc(20, 0);
//    parmods[2].setTcalc(27.5, 0);
//    
//    parmods[0].setTcalc(9, 1);
//    parmods[1].setTcalc(25, 1);
//    parmods[2].setTcalc(10, 1);
//    
    parmods[0].setTcalc(15, 0);
    parmods[1].setTcalc(20, 0);
    parmods[2].setTcalc(27.5, 0);
    
    if( horizon > 1){
    
    parmods[0].setTcalc(25, 1);
    parmods[1].setTcalc(30, 1);
    parmods[2].setTcalc(42, 1);

    }
    
    // SETTARE I PARAMETRI ALFA E BETA DIVERSI
    
   
    for (int h = 0; h < horizon; h++) {
        for(int i = 0; i < num_parmods; i++)
            for(int j = 0; j < num_parmods; j++){
                
                parmods[i].TcalcsPrediction[h][j] = parmods[j].TcalcsPrediction[h][j];
                
            }
    }
    
    
    for (int h = 0; h < horizon; h++) {
        
        cout << "Tcalc prediction for step " << h << " : ";
        
        for(int i = 0; i < num_parmods; i++){
           
            cout << parmods[0].TcalcsPrediction[h][i] << " " ;
            
        } 
        
        
        cout << endl;
    }
    
    // setting the parmod i ideal degree for each step h
    
//    for (int h = 0; h < horizon; h++) {
//        
//        for(int i = 0; i < num_parmods; i++){
//            
//            parmods[i].id = i;
//            
//            if (h != 0) {
//                parmods[i].idealDegree[h] = 12;
//            }
//            else parmods[i].setIdealDegree(h);
//            
//                        
//        } 
//    }
    
    
    parmods[0].idealDegree[0] = 5.50;
    parmods[0].idealDegree[1] = 5.60;
    parmods[1].idealDegree[0] = 13.5;
    parmods[1].idealDegree[1] = 15.50;
    parmods[2].idealDegree[0] = 10.30;
    parmods[2].idealDegree[1] = 10.50;

  
    
    
    for( int h = 0; h < horizon; h++){
        
        for(int i = 0; i < num_parmods; i++){
            
            for(int k = 0; k < num_parmods; k++)
                for(int j = 0; j < num_parmods; j++) {
                    
                    parmods[i].estimateCube[h].pastEstimate[k][j] = parmods[j].getIdealDegree(h);
                    parmods[i].initialState[j] = parmods[j].getIdealDegree(0);
                                        
                }
        }        
    }
    
    cout << endl;
    
    for (int i = 0; i < num_parmods; i++) {
        cout << "Parmod " << i << " initial degree " << parmods[i].initialState[i] << " " << endl;
    }   
    
    cout << endl;
    
        
    
        
    
    
    
    
           
    for(int h = 0; h < horizon ; h++){
        for(int k = 0; k < num_parmods; k++){
            
            cout << "Parmod " << h << " initial estimate " << " at step " << k << endl;
            
            for (int i = 0; i < num_parmods; i++) {
                
                for(int j = 0; j < num_parmods; j++){
                    
                    cout << parmods[k].estimateCube[h].pastEstimate[i][j] << " " ;
                    
                }
                cout << endl;
            }
            
            cout << endl;
        }
    }
    
    
    int counter = 0;
    
    while (counter < 500000) {
        
    
        
        // calculate local estimate
        
       
            for(int i = 0; i < num_parmods; i++)
                 for(int h = 0; h < horizon; h++)
                     parmods[i].calculateEstimate(counter, h);
        
        
        // distribute local estimates
        
        for(int h = 0; h < horizon; h++)
            
            for( int i = 0; i < num_parmods; i++){
                
                for(int j = 0; j < num_parmods; j++){
                    
                    parmods[i].receiveProfile(j, parmods[j].estimateCube[h].pastEstimate[j], h);                
                }
            }
        
        
        counter++;
        
    }
    
    
    
    
    
    
    for (int h = 0; h < horizon; h++) {
    
    
        for(int i = 0; i < num_parmods; i++){
            
            cout << "Parmod " << i << " estimate at step " << h << " : ";
            
            for (int j = 0; j < num_parmods; j++) {
                
                cout << parmods[i].estimateCube[h].pastEstimate[i][j] << " ";
                
            }           
            cout << endl;
        }        
        cout << endl;
    }
    
    double total_cost = parmods[0].getCost() + parmods[1].getCost() + parmods[2].getCost();
    
    cout << "Total cost : " << total_cost << " " << endl;
    
    return 0;
}

